package online.inote.naruto.utils.http;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.parser.Feature;
import lombok.Builder;
import okhttp3.Response;
import online.inote.naruto.exception.HttpException;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Objects;

/**
 * @description 请求结果
 * @author gaopengsui@creditease.cn
 * @date 2021/10/08 4:21 下午
 */
@Builder
public class Result {
  private Response response;
  private ResultConvertor convertor;
  private InputStream in;

  public boolean isSuccess() {
    return response.isSuccessful();
  }

  /**
   * 转为Bean
   *
   * @param type 类型
   * @param <T> 泛型对象
   * @return 指定Bean
   */
  public <T> T toBean(Type type) {
    if (response.isSuccessful()) {
      assert response.body() != null;
      return getConvertor().toBean(type, response.body().byteStream(), StandardCharsets.UTF_8);
    }

    throw new RuntimeException("对象转换失败");
  }

  /**
   * 转为Bean(fastJson)
   *
   * @param type 类型
   * @param features 特征
   * @param <T> 泛型对象
   * @return 指定Bean
   */
  public <T> T toBean(TypeReference<T> type, Feature... features) {
    if (response.isSuccessful()) {
      assert response.body() != null;
      try {
        return JSON.parseObject(getConvertor().mapping(response.body().string()), type, features);
      } catch (IOException e) {
        throw new HttpException("Http访问异常", e);
      }
    }
    throw new RuntimeException("对象转换失败");
  }

  /**
   * 转为对象集合(List)
   *
   * @param clazz 类型
   * @param <T> 泛型
   * @return List结果集合
   */
  public <T> List<T> toList(Class<T> clazz) {
    if (response.isSuccessful()) {
      assert response.body() != null;
      return getConvertor().toList(clazz, response.body().byteStream(), StandardCharsets.UTF_8);
    }

    throw new RuntimeException("对象转换失败");
  }

  public String getBody() throws IOException {
    return response.body().string();
  }

  private ResultConvertor getConvertor() {
    if (Objects.nonNull(this.convertor)) {
      return this.convertor;
    }

    return new DefaultResultConvertor();
  }
}
